package org.vacoor.xqq.ui.util;

import javax.swing.*;
import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.awt.image.ImageObserver;

/**
 * 常用图片操作工具
 *
 * @author Vacoor
 */
public abstract class ImageUtil {

    public static BufferedImage toBufferedImage(Image image, ImageObserver observer) {
        if (image instanceof BufferedImage) {
            return (BufferedImage) image;
        }

        ensureImageLoaded(image);
        int width = image.getWidth(observer);
        int height = image.getHeight(observer);
        if (width < 0 || height < 0) {
            return null;
        }

        BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = bufferedImage.createGraphics();
        g2d.drawImage(image, 0, 0, observer);
        g2d.dispose();
        return bufferedImage;
    }

    /**
     * 图片灰度化
     * 使用 {@link javax.swing.GrayFilter} 效果不是很理想
     * {@link #negative(java.awt.Image)}
     *
     * @param image
     * @return
     */
    public static Image gray(Image image) {
        return GrayFilter.createDisabledImage(image);
    }

    /**
     * 图片灰度化
     * 使用 {@link java.awt.image.ColorConvertOp}
     * 常规操作最好使用 {@link #gray(java.awt.Image)} 替代
     * 如果需要使用一些特殊的处理, eg: 平滑处理 {@link java.awt.RenderingHints#KEY_ANTIALIASING} 可以使用该方法
     *
     * @param image
     * @return
     */
    public static BufferedImage gray(BufferedImage image, RenderingHints hits) {
        return new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), hits).filter(image, null);
    }

    /**
     * 图片负片化
     *
     * @param image
     * @return
     */
    public static Image negative(Image image) {
        return NegativeFilter.createNegativeImage(image);
    }

    /**
     * 使用快速缩放算法缩放图像
     * {@link #resize(java.awt.Image, int, int, int)}
     */
    public static Image resize(Image image, Dimension size) {
        // return resize(image, size.width, size.height, Image.SCALE_SMOOTH); // 平滑度优先缩放
        return resize(image, size.width, size.height, Image.SCALE_FAST); // 快速缩放
    }

    /**
     * 图片缩放
     *
     * @param image
     * @param width
     * @param height
     * @param imageHits {@link Image#getScaledInstance(int, int, int)}
     * @return
     */
    public static Image resize(Image image, int width, int height, int imageHits) {
        return image.getScaledInstance(width, height, imageHits);
    }

    /**
     * 图片缩放
     * 该方法使用 {@link java.awt.geom.AffineTransform} 来执行缩放
     * {@link #resize(java.awt.Image, int, int, int)} 使用 {@link java.awt.image.ImageFilter } 缩放效率高很多
     *
     * @return
     * @deprecated
     */
    @Deprecated
    public static Image scale(BufferedImage image, int width, int height) {
        double sx = width / 1.0 / image.getWidth();
        double sy = height / 1.0 / image.getHeight();
        // AffineTransform transform = new AffineTransform();
        // transform.setToScale(sx, sy);
        AffineTransform transform = AffineTransform.getScaleInstance(sx, sy);
        AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
        return op.filter(image, null);
    }

    /**
     * {@link #drawWatermark(java.awt.Image, java.awt.Image, int, int, int, int, java.awt.image.ImageObserver)}
     */
    public static BufferedImage drawWatermark(Image image, Image watermark, int x, int y, ImageObserver observer) {
        ensureImageLoaded(watermark);
        return drawWatermark(image, watermark, x, y, watermark.getWidth(observer), watermark.getHeight(observer), observer);
    }

    /**
     * 在图片给定区域绘制水印图片
     *
     * @param image     原始图片
     * @param watermark 水印图片
     * @param x         起始 x 坐标
     * @param y         起始 y 坐标
     * @param width     水印宽度
     * @param height    水印高度
     * @param observer
     * @return
     */
    public static BufferedImage drawWatermark(Image image, Image watermark, int x, int y, int width, int height, ImageObserver observer) {
        ensureImageLoaded(image);
        ensureImageLoaded(watermark);
        int w = image.getWidth(observer);
        int h = image.getHeight(observer);
        BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
        Graphics g = img.getGraphics();
        g.drawImage(image, 0, 0, w - 1, h, observer);
        g.drawImage(watermark, x, y, width, height, observer);
        g.dispose();
        return img;
    }

    protected static void ensureImageLoaded(Image image) {
        ImageLoader.ensureImageLoaded(image);
    }
}
